/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package da;

import da.exceptions.IllegalOrphanException;
import da.exceptions.NonexistentEntityException;
import da.exceptions.PreexistingEntityException;
import da.exceptions.RollbackFailureException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entities.Department;
import entities.Account;
import entities.Complain;
import entities.Relation;
import java.util.ArrayList;
import java.util.List;
import entities.Reply;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;

/**
 *
 * @author THOHCGC00177
 */
public class ComplainJpaController implements Serializable {

    public ComplainJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Complain complain) throws PreexistingEntityException, RollbackFailureException, Exception {
        if (complain.getRelationList() == null) {
            complain.setRelationList(new ArrayList<Relation>());
        }
        if (complain.getReplyList() == null) {
            complain.setReplyList(new ArrayList<Reply>());
        }
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Department departmentId = complain.getDepartmentId();
            if (departmentId != null) {
                departmentId = em.getReference(departmentId.getClass(), departmentId.getId());
                complain.setDepartmentId(departmentId);
            }
            Account accountId = complain.getAccountId();
            if (accountId != null) {
                accountId = em.getReference(accountId.getClass(), accountId.getId());
                complain.setAccountId(accountId);
            }
            List<Relation> attachedRelationList = new ArrayList<Relation>();
            for (Relation relationListRelationToAttach : complain.getRelationList()) {
                relationListRelationToAttach = em.getReference(relationListRelationToAttach.getClass(), relationListRelationToAttach.getId());
                attachedRelationList.add(relationListRelationToAttach);
            }
            complain.setRelationList(attachedRelationList);
            List<Reply> attachedReplyList = new ArrayList<Reply>();
            for (Reply replyListReplyToAttach : complain.getReplyList()) {
                replyListReplyToAttach = em.getReference(replyListReplyToAttach.getClass(), replyListReplyToAttach.getId());
                attachedReplyList.add(replyListReplyToAttach);
            }
            complain.setReplyList(attachedReplyList);
            em.persist(complain);
            if (departmentId != null) {
                departmentId.getComplainList().add(complain);
                departmentId = em.merge(departmentId);
            }
            if (accountId != null) {
                accountId.getComplainList().add(complain);
                accountId = em.merge(accountId);
            }
            for (Relation relationListRelation : complain.getRelationList()) {
                Complain oldComplainIdOfRelationListRelation = relationListRelation.getComplainId();
                relationListRelation.setComplainId(complain);
                relationListRelation = em.merge(relationListRelation);
                if (oldComplainIdOfRelationListRelation != null) {
                    oldComplainIdOfRelationListRelation.getRelationList().remove(relationListRelation);
                    oldComplainIdOfRelationListRelation = em.merge(oldComplainIdOfRelationListRelation);
                }
            }
            for (Reply replyListReply : complain.getReplyList()) {
                Complain oldComplainIdOfReplyListReply = replyListReply.getComplainId();
                replyListReply.setComplainId(complain);
                replyListReply = em.merge(replyListReply);
                if (oldComplainIdOfReplyListReply != null) {
                    oldComplainIdOfReplyListReply.getReplyList().remove(replyListReply);
                    oldComplainIdOfReplyListReply = em.merge(oldComplainIdOfReplyListReply);
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            if (findComplain(complain.getId()) != null) {
                throw new PreexistingEntityException("Complain " + complain + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Complain complain) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Complain persistentComplain = em.find(Complain.class, complain.getId());
            Department departmentIdOld = persistentComplain.getDepartmentId();
            Department departmentIdNew = complain.getDepartmentId();
            Account accountIdOld = persistentComplain.getAccountId();
            Account accountIdNew = complain.getAccountId();
            List<Relation> relationListOld = persistentComplain.getRelationList();
            List<Relation> relationListNew = complain.getRelationList();
            List<Reply> replyListOld = persistentComplain.getReplyList();
            List<Reply> replyListNew = complain.getReplyList();
            List<String> illegalOrphanMessages = null;
            for (Relation relationListOldRelation : relationListOld) {
                if (!relationListNew.contains(relationListOldRelation)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Relation " + relationListOldRelation + " since its complainId field is not nullable.");
                }
            }
            for (Reply replyListOldReply : replyListOld) {
                if (!replyListNew.contains(replyListOldReply)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Reply " + replyListOldReply + " since its complainId field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (departmentIdNew != null) {
                departmentIdNew = em.getReference(departmentIdNew.getClass(), departmentIdNew.getId());
                complain.setDepartmentId(departmentIdNew);
            }
            if (accountIdNew != null) {
                accountIdNew = em.getReference(accountIdNew.getClass(), accountIdNew.getId());
                complain.setAccountId(accountIdNew);
            }
            List<Relation> attachedRelationListNew = new ArrayList<Relation>();
            for (Relation relationListNewRelationToAttach : relationListNew) {
                relationListNewRelationToAttach = em.getReference(relationListNewRelationToAttach.getClass(), relationListNewRelationToAttach.getId());
                attachedRelationListNew.add(relationListNewRelationToAttach);
            }
            relationListNew = attachedRelationListNew;
            complain.setRelationList(relationListNew);
            List<Reply> attachedReplyListNew = new ArrayList<Reply>();
            for (Reply replyListNewReplyToAttach : replyListNew) {
                replyListNewReplyToAttach = em.getReference(replyListNewReplyToAttach.getClass(), replyListNewReplyToAttach.getId());
                attachedReplyListNew.add(replyListNewReplyToAttach);
            }
            replyListNew = attachedReplyListNew;
            complain.setReplyList(replyListNew);
            complain = em.merge(complain);
            if (departmentIdOld != null && !departmentIdOld.equals(departmentIdNew)) {
                departmentIdOld.getComplainList().remove(complain);
                departmentIdOld = em.merge(departmentIdOld);
            }
            if (departmentIdNew != null && !departmentIdNew.equals(departmentIdOld)) {
                departmentIdNew.getComplainList().add(complain);
                departmentIdNew = em.merge(departmentIdNew);
            }
            if (accountIdOld != null && !accountIdOld.equals(accountIdNew)) {
                accountIdOld.getComplainList().remove(complain);
                accountIdOld = em.merge(accountIdOld);
            }
            if (accountIdNew != null && !accountIdNew.equals(accountIdOld)) {
                accountIdNew.getComplainList().add(complain);
                accountIdNew = em.merge(accountIdNew);
            }
            for (Relation relationListNewRelation : relationListNew) {
                if (!relationListOld.contains(relationListNewRelation)) {
                    Complain oldComplainIdOfRelationListNewRelation = relationListNewRelation.getComplainId();
                    relationListNewRelation.setComplainId(complain);
                    relationListNewRelation = em.merge(relationListNewRelation);
                    if (oldComplainIdOfRelationListNewRelation != null && !oldComplainIdOfRelationListNewRelation.equals(complain)) {
                        oldComplainIdOfRelationListNewRelation.getRelationList().remove(relationListNewRelation);
                        oldComplainIdOfRelationListNewRelation = em.merge(oldComplainIdOfRelationListNewRelation);
                    }
                }
            }
            for (Reply replyListNewReply : replyListNew) {
                if (!replyListOld.contains(replyListNewReply)) {
                    Complain oldComplainIdOfReplyListNewReply = replyListNewReply.getComplainId();
                    replyListNewReply.setComplainId(complain);
                    replyListNewReply = em.merge(replyListNewReply);
                    if (oldComplainIdOfReplyListNewReply != null && !oldComplainIdOfReplyListNewReply.equals(complain)) {
                        oldComplainIdOfReplyListNewReply.getReplyList().remove(replyListNewReply);
                        oldComplainIdOfReplyListNewReply = em.merge(oldComplainIdOfReplyListNewReply);
                    }
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = complain.getId();
                if (findComplain(id) == null) {
                    throw new NonexistentEntityException("The complain with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Complain complain;
            try {
                complain = em.getReference(Complain.class, id);
                complain.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The complain with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Relation> relationListOrphanCheck = complain.getRelationList();
            for (Relation relationListOrphanCheckRelation : relationListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Complain (" + complain + ") cannot be destroyed since the Relation " + relationListOrphanCheckRelation + " in its relationList field has a non-nullable complainId field.");
            }
            List<Reply> replyListOrphanCheck = complain.getReplyList();
            for (Reply replyListOrphanCheckReply : replyListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Complain (" + complain + ") cannot be destroyed since the Reply " + replyListOrphanCheckReply + " in its replyList field has a non-nullable complainId field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Department departmentId = complain.getDepartmentId();
            if (departmentId != null) {
                departmentId.getComplainList().remove(complain);
                departmentId = em.merge(departmentId);
            }
            Account accountId = complain.getAccountId();
            if (accountId != null) {
                accountId.getComplainList().remove(complain);
                accountId = em.merge(accountId);
            }
            em.remove(complain);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Complain> findComplainEntities() {
        return findComplainEntities(true, -1, -1);
    }

    public List<Complain> findComplainEntities(int maxResults, int firstResult) {
        return findComplainEntities(false, maxResults, firstResult);
    }

    private List<Complain> findComplainEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Complain.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Complain findComplain(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Complain.class, id);
        } finally {
            em.close();
        }
    }

    public int getComplainCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Complain> rt = cq.from(Complain.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
